#ifndef GRAPH_H
#define GRAPH_H

#include <iostream>
#include "climits"

enum Graph_Color {black, white};

struct Graph_Node
{
	Graph_Node(int d = INT_MIN, int w = INT_MIN) : data(d), weight(w) ,next(0), color(white) {}

	Graph_Node& operator=(const Graph_Node& node)
	{
		this->color=node.color;
		this->data=node.data;
		this->weight=node.weight;
		if (node.next)
		{
			this->next=new Graph_Node();
			(*this->next)=(*node.next);
		}
		return *this;
	}

	friend std::ostream& operator << (std::ostream& str, const Graph_Node& node)
	{
		str << "(" << node.data << ", ";
		if (node.weight==INT_MIN) str << "-inf";
		else if (node.weight==INT_MAX) str << "+inf";
		else str << node.weight;
		str << ")";
		return str;
	}

	bool operator==(const Graph_Node& node) const
	{
		return node.data==this->data;
	}

	bool operator!=(const Graph_Node& node) const
	{
		return !(node==*this);
	}

	int data;
	int weight;
	Graph_Node *next;
	Graph_Color color;
};

class Graph
{
protected:

	unsigned int size;

        int getHashCode(const int& node) const;
	int getHashCode(const Graph_Node& data) const;

	Graph_Node *nodes;

public:

	Graph(unsigned int s = 0);

	Graph(const Graph& graph);

	void loadFromFile(const std::string& file_name);

	unsigned int getSize() const;

	friend std::ostream& operator << (std::ostream& str, const Graph& g)
	{
		for (unsigned int i=1;i<g.size;++i)
		{
			str << g.nodes[i] << " : ";
			Graph_Node *p=g.nodes[i].next;
			while (p)
			{
				str << (*p);
				p=p->next;
			}
			str << std::endl;
		}
		return str;
	}

	int getIndexOf(const Graph_Node& node) const;

	Graph_Node& operator[](unsigned int index);
	const Graph_Node& operator[](unsigned int index) const;

	Graph_Node& operator[](const Graph_Node& node);
	const Graph_Node& operator[](const Graph_Node& node) const;
};

#endif // GRAPH_H
